﻿using HtmlAgilityPack;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static WXTao.Form2;

namespace WXTao
{
    class WeixinWeb
    {
        private static DateTime timeStampStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        private string uuid = "";
        //private string webwx_data_ticket, webwx_auth_ticket;
        private string skey, wxsid, wxuin, pass_ticket;
        private WeixinUser user = new WeixinUser();
        List<Cookie> cookies;
        Dictionary<JToken, JToken> SyncKey_dic;
        
        public WeixinWeb()
        {
            long timer = (long)(DateTime.Now - timeStampStartTime).TotalMilliseconds;
            string task = getStringData("https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=" + timer);


            string[] ss = task.Split(';');
            uuid = ss[1].Replace(" window.QRLogin.uuid = \"", "").Replace("\"", "");
        }

        private string getStringData(string url)
        {
            try
            {
                using (var client = new HttpClient())
                {
                    var responseString = client.GetStringAsync(url);
                    return responseString.Result;
                }
            }
            catch (Exception e)
            {
                return e.Message.ToString();
            }
        }

        public async Task<string> getData(string url)
        {
            try
            {
                var handler = new HttpClientHandler() { UseCookies = false };
                using (var client = new HttpClient(handler))
                {
                    client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36");//加头
                    var message = new HttpRequestMessage(HttpMethod.Get, url);
                    string cookie = "";

                    if (cookies != null)
                    {
                        foreach (var item in cookies)
                        {
                            cookie += item.Name + "=" + item.Value + ";";

                        }
                    }
                    message.Headers.Add("Cookie", cookie);
                    var response = await client.SendAsync(message);
                    string result = await response.Content.ReadAsStringAsync();
                    return result;
                }
            }
            catch (Exception e)
            {
                return e.Message.ToString();
            }
        }

        private async Task<string> PostData(string url, string param)
        {
            try
            {
                StringContent content = new StringContent(param, System.Text.Encoding.UTF8, "application/json");
                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36");//加头
                    var response = await client.PostAsync(url, content);

                    string result = await response.Content.ReadAsStringAsync();
                    return result;
                }
            }
            catch (Exception e)
            {
                return e.Message.ToString();
            }

        }


        public async Task<string> Getcookie(string url)
        {
            try
            {
                StringBuilder sb_cookie = new StringBuilder();

                CookieContainer cookieContainer = new CookieContainer();
                var uri = new Uri(url);
                var handler = new HttpClientHandler();
                handler.CookieContainer = cookieContainer;
                HttpClient client = new HttpClient(handler);
                client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36");//加头
                var responseString = await client.GetStringAsync(uri);
                cookies = cookieContainer.GetCookies(uri).Cast<Cookie>().ToList();
                //foreach (var item in cookies)
                //{
                //    if (item.Name.Equals("webwx_data_ticket"))
                //    {
                //        webwx_data_ticket = item.Value;
                //    }
                //    else if (item.Name.Equals("webwx_auth_ticket"))
                //    {
                //        webwx_auth_ticket = item.Value;
                //    }

                //}

                return responseString;
            }
            catch
            {
                return String.Empty;
            }

        }


        public string getUUID()
        {
            return uuid;
        }

        private LoginCallback login_cb;
        public void weixinLogin(LoginCallback callBack)
        {
            login_cb = callBack;
            ThreadStart thStart = new ThreadStart(login);//threadStart委托 
            Thread thread = new Thread(thStart);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Priority = ThreadPriority.Highest;
            thread.IsBackground = true; //关闭窗体继续执行
            thread.Start();
        }

        private void login()
        {
            string ret = "";
            string data = "";
            Task<string> task;
            while (true)
            {
                long timer = (long)(DateTime.Now - timeStampStartTime).TotalMilliseconds;
                data = getStringData("https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&tip=0&r=728200355&_=" + timer + "&uuid=" + uuid);

                string[] ss = data.Split(';');
                if (ss[0].Contains("200"))
                {
                    ret = ss[1].Replace("window.redirect_uri=\"", "").Replace("\"", "").Replace("\n", "");
                    task = Getcookie(ret + "&fun=new&version=v2");
                    task.Wait();

                    data = task.Result;
                    HtmlDocument doc = new HtmlDocument();
                    doc.LoadHtml(data);
                    HtmlNode node = doc.DocumentNode;
                    HtmlNode div = node.SelectNodes("//ret")[0];
                    ret = div.InnerText;
                    skey = node.SelectNodes("//skey")[0].InnerText;
                    wxsid = node.SelectNodes("//wxsid")[0].InnerText;
                    wxuin = node.SelectNodes("//wxuin")[0].InnerText;
                    pass_ticket = node.SelectNodes("//pass_ticket")[0].InnerText;
                    login_cb("success");
                    break;
                }
                else if (ss[0].Contains("201"))
                {
                    ret = ss[1] + ";" + ss[2];
                    data = ret.Replace("window.userAvatar = \'", "").Replace("\'", "").Replace("\n", "");
                    User.Head_img = data;
                    login_cb("loading");
                }
                else 
                {
                    if(!User.Head_img.Equals(""))
                    {
                        User.Head_img = "";
                        login_cb("failed");
                    }
                        
                }

               Thread.Sleep(100);
            }

            if (ret.Equals("0"))
            {
                
                string s = "{\"BaseRequest\":{\"Uin\":\"" + wxuin +
                    "\",\"Sid\":\"" + wxsid +
                    "\",\"Skey\":\"" + skey +
                    "\",\"DeviceID\":\"e671277198302499\"}}";
                task = PostData("https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=719072486&pass_ticket=" + pass_ticket, s);
                task.Wait();

                data = task.Result.Replace("\n", "");
                JObject jObj = JObject.Parse(data);
                if (jObj != null && jObj["BaseResponse"]["Ret"].ToString().Equals("0"))
                {
                    User.User_name = jObj["User"]["NickName"].ToString();
                    //JArray SyncKey = jObj["SyncKey"].Value<JArray>("List");
                    SyncKey_dic = jObj["SyncKey"].Value<JArray>("List").ToDictionary(t => t["Key"], t => t["Val"]);
                    
                }
            }
        }

        public void getHeadImg()
        {

        }

        private MsgCallback msg_cb;
        public void startGetMessage(MsgCallback callback)
        {
            msg_cb = callback;
            ThreadStart thStart = new ThreadStart(getMessage);//threadStart委托 
            Thread thread = new Thread(thStart);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Priority = ThreadPriority.Highest;
            thread.IsBackground = true; //关闭窗体继续执行
            thread.Start();
        }

        public void getMessage()
        {
            string data = "";
            Task<string> task;
            JObject jObj;
            while (true)
            {
                long timer = (long)(DateTime.Now - timeStampStartTime).TotalMilliseconds;
                string url = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?";
                string param = "r=" + timer + "&skey=" + skey + "&sid=" + wxsid
                    + "&uin=" + wxuin + "&deviceid=e671277198302499"
                    + "&synckey=1_" + SyncKey_dic[1] + "%7C2_" + SyncKey_dic[2]
                    + "%7C3_" + SyncKey_dic[3] + "%7C1000_" + SyncKey_dic[1000]
                    + "&_=" + timer;

                task = getData(url + param);
                task.Wait();
                data = task.Result.Replace("window.synccheck=", "");
                if (data != null)
                {
                    jObj = JObject.Parse(data);
                    if (jObj["retcode"].ToString().Equals("0") && jObj["selector"].ToString().Equals("2"))
                    {
                        url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=" + wxsid + "&skey=" + skey + "&lang=zh_CN&pass_ticket=" + pass_ticket;
                        JObject jO_BaseRequest = new JObject();
                        jO_BaseRequest.Add("Uin", wxuin);
                        jO_BaseRequest.Add("Sid", wxsid);
                        jO_BaseRequest.Add("Skey", skey);
                        jO_BaseRequest.Add("DeviceID", "e671277198302499");

                        JObject jO_rr = new JObject();
                        jO_rr.Add("rr", timer);

                        JArray ja_List = new JArray();
                        foreach (var item in SyncKey_dic)
                        {
                            JObject jo = new JObject();
                            jo.Add("Key", item.Key);
                            jo.Add("Val", item.Value);
                            ja_List.Add(jo);
                        }

                        JObject jO_SyncKey = new JObject();
                        jO_SyncKey.Add("Count", SyncKey_dic.Count);
                        jO_SyncKey.Add("List", ja_List);

                        JObject root = new JObject();
                        root.Add("BaseRequest", jO_BaseRequest);
                        root.Add("rr", jO_rr);
                        root.Add("SyncKey", jO_SyncKey);

                        param = root.ToString().Replace("\n", "").Replace(" ", "").Replace("\r", "");
                        task = PostData(url, param);
                        task.Wait();

                        data = task.Result.Replace("\n", "");
                        jObj = JObject.Parse(data);
                        if (jObj != null && jObj["BaseResponse"]["Ret"].ToString().Equals("0"))
                        {
                            SyncKey_dic = jObj["SyncKey"].Value<JArray>("List").ToDictionary(t => t["Key"], t => t["Val"]);
                            user.Data = task.Result;
                            msg_cb("success");
                        }
                        

                    }
                }

            }
        }
        

        internal WeixinUser User { get => user; set => user = value; }

        private GroupCallback group_cb;
        public void getConetct(GroupCallback callback)
        {
            group_cb = callback;
            ThreadStart thStart = new ThreadStart(getConetctThread);//threadStart委托 
            Thread thread = new Thread(thStart);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Priority = ThreadPriority.Highest;
            thread.IsBackground = true; //关闭窗体继续执行
            thread.Start();

        }

        
        private void getConetctThread()
        {
            long timer = (long)(DateTime.Now - timeStampStartTime).TotalMilliseconds;
            string url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=" + pass_ticket
                + "&r=" + timer + "&seq=0&skey=" + skey;
            Task<string> task = getData(url);
            task.Wait();

            user.Data = task.Result.Replace("\n", "");
            JObject jObject = JObject.Parse(task.Result);
            user.Groups.Clear();
            foreach (var item in jObject["MemberList"])
            {
                if(item["UserName"].ToString().StartsWith("@@"))
                {
                    user.Groups.Add(item["NickName"].ToString(), item["UserName"].ToString());
                }
            }
            group_cb(user.Data);
            
        }
    }
}
